//
// Created by 吴喆 on 2020/3/3.
//

#include <iostream>
#include <sstream>
#include <chrono>
#include <iomanip>
#include "Input.h"
#include "../util/GameUtil.h"

Input* Input::input = new Input();


// 必须进行修饰，因为成员函数隐含一个this指针，所以无法作为glfwSetKeyCallback函数的参数
void keyCallbackWrapper(GLFWwindow *window, int key, int scanCode, int action, int mods) {
    Input::getInstance()->keyCallback(window, key, scanCode, action, mods);
}

void cursorCallbackWrapper(GLFWwindow *window, double posX, double posY) {
    Input::getInstance()->cursorCallback(window, posX, posY);
}

void mouseClickCallbackWrapper(GLFWwindow *window, int button, int action, int mods) {
    Input::getInstance()->mouseClickCallback(window, button, action, mods);
}

void Input::initCallback(GLFWwindow *win, std::pair<int, int> pos) {
    // 设置光标为中心点
    glfwSetCursorPos(win, pos.first, pos.second);
    this->cursorCallback(win, pos.first, pos.second);
    glfwSetKeyCallback(win, keyCallbackWrapper);
    glfwSetCursorPosCallback(win, cursorCallbackWrapper);
    glfwSetMouseButtonCallback(win, mouseClickCallbackWrapper);

}

glm::vec2 Input::getMousePos() {
    cursorCallback(nullptr, 0,0);
    return glm::vec2(posX, posY);

}

void Input::keyCallback(GLFWwindow *window, int key, int scanCode, int action, int mods) {
    if(key == GLFW_KEY_F10 && action == GLFW_PRESS) {
        auto t = std::chrono::system_clock::to_time_t(std::chrono::system_clock::now());

        std::string fileName("./screenshot");
        std::stringstream ss;
        ss << std::put_time(std::localtime(&t), "%F-%T");
        fileName.append(ss.rdbuf()->str());
        fileName.append(".bmp");

        GameUtil::screenShort(fileName.data());
        return;
    }
    auto* result = new KeyEvent(key, scanCode, action, mods);
    if (this->keyMap[key] != nullptr) {
        delete this->keyMap[key];
    }
    this->keyMap[key] = result;
    notifyKeyboardClick(result);
}

void Input::mouseClickCallback(GLFWwindow *window, int button, int action, int mods) {
    auto* result = new MouseEvent(button, action, mods);
    if (this->keyMap[button] != nullptr) {
        delete this->keyMap[button];
    }
    this->mouseMap[button] = result;
    notifyMouseClick(result);

}

void Input::cursorCallback(GLFWwindow *window, double posX, double posY) {
//    std::cout << posX << " " << posY << std::endl;
    this->posY = posY;
    this->posX = posX;
    notifyCursorMove(posX, posY);
}